package com.example.searchjavaapi.searcher;

import com.example.searchjavaapi.common.DocInfo;
import com.example.searchjavaapi.index.Index;

import com.example.searchjavaapi.parser.Parser;
import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;


class WeightComparator implements Comparator<Index.Weight> {

    @Override
    public int compare(Index.Weight o1, Index.Weight o2) {
        //如果o1<o2返回一个<0的数字
        //如果o1>o2返回一个>0的数字
        //如果o1==o2返回0
        return o2.weight-o1.weight;
    }
}


//核心搜索过程
@Service
public class Searcher {

    private Index index = new Index();

    public Searcher() throws IOException {
//        Parser.loadIndex();
//        index.build("E://raw_data.txt");
        index.build("/root/javadoc/raw_data.txt");//服务器环境
    }

    public List<Result> search(String query){
        //1.分词，针对查询词进行分词
        List<Term> terms = ToAnalysis.parse(query).getTerms();
        //2.触发，这对查询词的分词结果，依次查询倒排索引，得到一大堆相关的docId
        //这个ArrayList中保存每个分词的结果
        ArrayList<Index.Weight> allTokenResult = new ArrayList<>();
        for (Term term:terms){
            //此处得到的words就已经是全小写的内容了，索引的内容也是小写的
            String word = term.getName();
            List<Index.Weight> invertedList =  index.getInvertedIndex(word);
            if (invertedList==null){
                //说明用户输入的这部分词很生僻，在所有文档中都不存在
                continue;
            }
            allTokenResult.addAll(invertedList);
        }
        //3.按照权重进行降序排序
        allTokenResult.sort(new WeightComparator());
        //4.根据刚才查找到的DocId在正排中查找DocInfo，包装成Result
        ArrayList<Result> results = new ArrayList<>();
        for(Index.Weight weight : allTokenResult){
            //根据weight中包含的docId找到对应的DocInfo对象
            DocInfo docInfo = index.getDocInfo(weight.docId);
            Result result = new Result();
            result.setTitile(docInfo.getTitle());
            result.setShowUrl(docInfo.getUrl());
            result.setClickUrl(docInfo.getUrl());
            //GenDesc 做的事是从正文中摘取一段摘要信息，根据当前这次词，找到这个词在正文中的位置
            //再把这个位置周围的文本都获取到，得到了一个片段
            result.setDesc(GenDesc(docInfo.getContnet(),weight.word));
            results.add(result);
        }
        return results;

    }

    //这个方法是根据当前的词，提取正文中的一部分内容作为描述
    private String GenDesc(String contnet, String word) {
        //1.查找word在content出现的位置
        //word里面的内容已经是全小写了，content里面还是大小写都有
        int firstPos = contnet.toLowerCase().indexOf(word);
        if (firstPos == -1){
            //极端情况下，某个词只在标题中出现了，而没在正文中出现，在正文中肯定找不到
            //这种情况非常少见
            return "";
        }
        //从firstPos开始，往前找60个字符，作为描述的开始，如果前面不足60，就从正文头部开始
        int descBeg = firstPos<60?0:firstPos-60;
        //从描述开始往后找160个字符，作为描述内容，就把剩下的都算上
        if (descBeg+160>contnet.length()){
            return contnet.substring(descBeg);
        }
        return contnet.substring(descBeg,descBeg+160)+"...";


    }


}

